package org.xwalk.core;


import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;



public class XWalkNativeExtensionLoader   {

    private ArrayList<Object> constructorTypes;
    private ArrayList<Object> constructorParams;
    private ReflectMethod postWrapperMethod;


    private XWalkCoreWrapper coreWrapper;
    private Object bridge;

    protected Object getBridge() {
        return bridge;
    }


    public XWalkNativeExtensionLoader() {
        constructorTypes = new ArrayList<Object>();
        constructorParams = new ArrayList<Object>();

        reflectionInit();
    }

    /**
     * register path of native extensions.
     * @param path the path of the extension.
     */
    public void registerNativeExtensionsInPath(String path) {
        try {
            registerNativeExtensionsInPathStringMethod.invoke(path);
        } catch (UnsupportedOperationException e) {
            if (coreWrapper == null) {
                throw new RuntimeException("Crosswalk's APIs are not ready yet");
            } else {
                XWalkCoreWrapper.handleRuntimeError(e);
            }
        }
        
    }

    private ReflectMethod registerNativeExtensionsInPathStringMethod = new ReflectMethod(null, "registerNativeExtensionsInPath");


    void reflectionInit() {
        XWalkCoreWrapper.initEmbeddedMode();

        coreWrapper = XWalkCoreWrapper.getInstance();
        if (coreWrapper == null) {
            XWalkCoreWrapper.reserveReflectObject(this);
            return;
        }

        int length = constructorTypes.size();
        Class<?>[] paramTypes = new Class<?>[length+1];
        for (int i = 0; i < length; ++i) {
            Object type = constructorTypes.get(i);
            if (type instanceof String) {
                paramTypes[i] = coreWrapper.getBridgeClass((String) type);
                constructorParams.set(i, coreWrapper.getBridgeObject(constructorParams.get(i)));
            } else if (type instanceof Class<?>) {
                paramTypes[i] = (Class<?>) type;
            } else {
                assert(false);
            }
        }

        paramTypes[length] = Object.class;
        constructorParams.add(this);

        ReflectConstructor constructor = new ReflectConstructor(
                coreWrapper.getBridgeClass("XWalkNativeExtensionLoaderBridge"), paramTypes);
        try {
            bridge = constructor.newInstance(constructorParams.toArray());
        } catch (UnsupportedOperationException e) {
            return;
        }

        if (postWrapperMethod != null) postWrapperMethod.invoke();

        registerNativeExtensionsInPathStringMethod.init(bridge, null,
                "registerNativeExtensionsInPathSuper", String.class);
    }

}
